#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdint.h>

#include "hook.h"
#include "fd_manage.h"


namespace qtch{

static Logger::ptr logger = QTCH_LOG_NAME("system");

FdCtx::FdCtx(int fd):m_fd(fd){
    init();
}

FdCtx::~FdCtx(){

}

bool FdCtx::init(){
    if(m_isInit){
        return true;
    }
    m_recvTimeout = -1;
    m_sendTimeout = -1;
    struct stat fd_stat;
    if(fstat(m_fd, &fd_stat) == -1){
        m_isInit = false;
        m_isSocket = false;
    }
    else{
        m_isInit = true;
        m_isSocket = S_ISSOCK(fd_stat.st_mode);
    }

    if(m_isSocket){
        int flag = fcntl(m_fd,F_GETFL);
        m_sysNonblock = true;
        if(!(flag & O_NONBLOCK)){
            fcntl(m_fd,F_SETFL,flag| O_NONBLOCK);
        }
    }
    else{
        m_sysNonblock = false;
    }
    m_userNonblock = false;
    m_isClosed = false;
    return m_isInit;
}

void FdCtx::setTimeout(int type,uint64_t v){
    if(type == SO_RCVTIMEO){
        m_recvTimeout = v;
    }
    else{
        m_sendTimeout = v;
    }
}

uint64_t FdCtx::getTimeout(int type){
    if(type == SO_RCVTIMEO){
        return m_recvTimeout;
    }
    else{
        return m_sendTimeout;
    }
}

FdManager::FdManager(){
    m_datas.resize(64);
}

FdCtx::ptr FdManager::get(int fd, bool auto_create){
    if(fd == -1){
        return nullptr;
    }
    {
        RWMutexType::ReadLock lock(m_mutex);
        if((int)m_datas.size() <= fd){
            if(auto_create == false){
                return nullptr;
            }
        }
        else{
            if(m_datas[fd] || !auto_create){
                return m_datas[fd];
            }
        }
    }

    FdCtx::ptr ctx(new FdCtx(fd));
    RWMutexType::WriteLock lock(m_mutex);
    if(fd >= (int)m_datas.size()){
        m_datas.resize(fd*1.5);
    }
    m_datas[fd] = ctx;
    return m_datas[fd];
}

void FdManager::del(int fd){
    RWMutexType::WriteLock lock(m_mutex);
    if(fd >= (int)m_datas.size()){
        return;
    }
    m_datas[fd].reset();
}




}
